package com.jhhc.baseframework.data.Oj_Base;

import com.google.gson.Gson;
import java.util.Iterator;
import java.util.Map;
import java.util.Map.Entry;
import org.easymock.EasyMock;
import org.easymock.IMocksControl;
import org.junit.Before;
import org.junit.Rule;
import org.junit.rules.ExpectedException;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.mock.web.MockHttpServletResponse;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringRunner;
import org.springframework.test.context.web.WebAppConfiguration;
import org.springframework.test.web.servlet.MockMvc;
import org.springframework.test.web.servlet.ResultActions;
import org.springframework.test.web.servlet.request.MockHttpServletRequestBuilder;
import org.springframework.test.web.servlet.setup.MockMvcBuilders;
import org.springframework.web.context.WebApplicationContext;
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.*;

/**
 * 对于使用spring mvc的controller，只需要测试url是否走得通
 * @author yecq
 */
@RunWith(SpringRunner.class)
@WebAppConfiguration(value = "file:src/test/webapp")        // 默认是 file: src/main/webapp 下
@ContextConfiguration(locations = {"file:src/test/webapp/WEB-INF/applicationContext.xml", "file:src/test/webapp/WEB-INF/dispatcher-servlet.xml"})
public class JustHttpBase {
    @Autowired
    protected WebApplicationContext wac;

    protected MockMvc mockMvc;

    @Rule
    public ExpectedException expectedEx = ExpectedException.none();

    // mock对象，这个东西很难用
    protected IMocksControl mocksControl;

    protected JustHttpBase() {
        this.mocksControl = EasyMock.createStrictControl();
    }

    @Before
    public void before() {
        this.mockMvc = MockMvcBuilders.webAppContextSetup(this.wac).build();
    }

    //总的方法，仅返回http状态
    protected int executeHttp(String method, String url, Map<String, Object> param) {
        if (method == null || method.trim().equals("") || url == null) {
            throw new IllegalArgumentException("参数错误");
        }
        method = method.trim();
        MockHttpServletRequestBuilder builder = null;
        try {
            if (method.equalsIgnoreCase("get")) {
                builder = get(url);
            } else if (method.equalsIgnoreCase("post")) {
                builder = post(url);
            } else if (method.equalsIgnoreCase("put")) {
                builder = put(url);
            } else if (method.equalsIgnoreCase("delete")) {
                builder = delete(url);
            } else {
                throw new IllegalArgumentException("只支持get、post、put、delete方法");
            }

            if (param != null) {
                Iterator<Entry<String, Object>> ite = param.entrySet().iterator();
                while (ite.hasNext()) {
                    Entry<String, Object> ent = ite.next();
                    // 如果String也转成json，会额外加一对引号
                    String pp = null;
                    Object v = ent.getValue();
                    if (v.getClass().equals(String.class)) {
                        pp = (String) v;
                    } else {
                        pp = new Gson().toJson(v);
                    }
                    builder.param(ent.getKey(), pp);
                }
            }

            ResultActions actions = this.mockMvc.perform(builder.accept("application/json;charset=utf-8"));
            MockHttpServletResponse response = actions.andReturn().getResponse();

            // MockMvc貌似有一个bug，对于不存在的url，会返回200，而不是404，但http body为空，所以这里做一个转换
            int httpStatus = response.getStatus();
            String httpBody = response.getContentAsString();
            if (httpStatus == 200 && httpBody.equals("")) {
                httpStatus = 404;
            }
            return httpStatus;
        } catch (Throwable ex) {
            throw new IllegalStateException(ex);
        }
    }

    public int doGet(String url, Map<String, Object> param) {
        return executeHttp("get", url, param);
    }

    public int doGet(String url) {
        return doGet(url, null);
    }

    public int doPost(String url, Map<String, Object> param) {
        return executeHttp("post", url, param);
    }

    public int doPost(String url) {
        return doPost(url, null);
    }

    public int doPut(String url, Map<String, Object> param) {
        return executeHttp("put", url, param);
    }

    public int doPut(String url) {
        return doPut(url, null);
    }

    public int doDelete(String url, Map<String, Object> param) {
        return executeHttp("delete", url, param);
    }

    public int doDelete(String url) {
        return doDelete(url, null);
    }
}
